package cn.kicsy.www.anonymous_bbs.service;

import cn.kicsy.www.anonymous_bbs.config.AutoBanConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * CC攻击检测服务
 * 用于跟踪和检测疑似CC攻击的IP地址
 */
@Service
public class CcAttackDetectionService {
    
    private static final Logger logger = LoggerFactory.getLogger(CcAttackDetectionService.class);
    
    // 使用ConcurrentHashMap存储IP地址的请求计数和时间戳
    // Key: IP地址, Value: 包含请求计数和最后请求时间的对象
    private final Map<String, IpRequestCounter> ipRequestCounters = new ConcurrentHashMap<>();
    
    @Autowired
    private AutoBanConfig autoBanConfig;
    
    @Autowired
    private BanService banService;
    
    /**
     * 记录IP请求并检查是否需要自动封禁
     * @param ipAddress IP地址
     * @return 如果IP被封禁则返回true，否则返回false
     */
    public boolean recordRequestAndCheckBan(String ipAddress) {
        // 如果自动封禁功能未启用，则直接返回false
        if (!autoBanConfig.isEnabled()) {
            return false;
        }
        
        // 如果IP地址为空，则直接返回false
        if (ipAddress == null || ipAddress.trim().isEmpty()) {
            return false;
        }
        
        // 检查IP是否已经被封禁
        if (banService.isBanned(ipAddress)) {
            return true;
        }
        
        // 获取或创建IP请求计数器
        IpRequestCounter counter = ipRequestCounters.computeIfAbsent(ipAddress, k -> new IpRequestCounter());
        
        // 记录请求
        boolean shouldBan = counter.recordRequestAndCheckExceed(autoBanConfig.getMaxRequestsPerMinute());
        
        // 如果请求频率超过阈值，则自动封禁IP
        if (shouldBan) {
            logger.warn("IP {} 请求频率超过阈值，自动封禁", ipAddress);
            banService.banTemporarily(ipAddress, autoBanConfig.getBanReason(), autoBanConfig.getBanDurationHours());
            
            // 从计数器中移除该IP，避免重复封禁
            ipRequestCounters.remove(ipAddress);
            
            return true;
        }
        
        return false;
    }
    
    /**
     * 清理过期的请求计数器
     * 定期调用此方法以防止内存泄漏
     */
    public void cleanupExpiredCounters() {
        ipRequestCounters.entrySet().removeIf(entry -> {
            IpRequestCounter counter = entry.getValue();
            return counter.isExpired();
        });
    }
    
    /**
     * IP请求计数器内部类
     */
    private static class IpRequestCounter {
        private final AtomicInteger requestCount = new AtomicInteger(0);
        private volatile LocalDateTime lastRequestTime;
        private volatile LocalDateTime windowStartTime;
        
        public IpRequestCounter() {
            this.windowStartTime = LocalDateTime.now();
            this.lastRequestTime = LocalDateTime.now();
        }
        
        /**
         * 记录请求并检查是否超过阈值
         * @param maxRequestsPerMinute 每分钟最大请求数
         * @return 如果超过阈值则返回true，否则返回false
         */
        public synchronized boolean recordRequestAndCheckExceed(int maxRequestsPerMinute) {
            LocalDateTime now = LocalDateTime.now();
            
            // 如果距离上次请求已经超过1分钟，则重置计数器
            if (now.minusMinutes(1).isAfter(windowStartTime)) {
                requestCount.set(0);
                windowStartTime = now;
            }
            
            // 记录请求
            lastRequestTime = now;
            int currentCount = requestCount.incrementAndGet();
            
            // 检查是否超过阈值
            return currentCount > maxRequestsPerMinute;
        }
        
        /**
         * 检查计数器是否已过期（超过5分钟没有请求）
         * @return 如果已过期则返回true，否则返回false
         */
        public boolean isExpired() {
            return lastRequestTime != null && LocalDateTime.now().minusMinutes(5).isAfter(lastRequestTime);
        }
    }
}